
#ifndef CXTHREAD_H_INC
#define CXTHREAD_H_INC
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include "list_item.h"
#include "ndata.h"


class CxLock {
protected:
	SemaphoreHandle_t m_lock;

public:
	CxLock(void);
	virtual ~CxLock();

	virtual bool WaitFor(uint32_t msout);
	virtual void Release(void);
};

//临界区
class CxSection {
protected:
  SemaphoreHandle_t m_cs;

public:
  CxSection(void);
  virtual ~CxSection();

  virtual bool TryEnter(void);   
  virtual void Enter(void);
  virtual void Leave(void);
};




class CxReturn {
protected:
	SemaphoreHandle_t	m_hRetSem;
	bool			m_lastPendOk;
public:
	CxReturn(void);
	virtual ~CxReturn();
	virtual bool IsLastPendCompleted(uint32_t msout = portMAX_DELAY);
	virtual bool Pend(uint32_t msout = portMAX_DELAY);
	virtual void Post(void);		
};



class CxCall {
protected:
	SemaphoreHandle_t 	m_hCallSem;
	uint16_t				m_cmdId;	
	SemaphoreHandle_t 	m_hRetSem;
	uint32_t				m_ret;			
public:
	CxCall(void);
	virtual ~CxCall();
	virtual bool WaitLastReturn(uint32_t *pRet, uint32_t msout=100);
	virtual void Post(uint16_t cmdId);			
	virtual bool Received(uint16_t *pCmdId);
	virtual void PostReturn(uint32_t dvRet);	
};

class ReturnData {
public:
    uint16_t 	m_error;
    Ndata*	m_result;
    ReturnData(Ndata* result)	{ m_error = 0x0000, m_result = result; }
    virtual ~ReturnData()		{  }
};


class CxReq : ListItem {
protected:
    WORD		m_code;
    NPack* m_arg;
    ReturnData* m_pReturnData;			// 调用方创建和释放
    CxReturn* m_pSyncReturn;			// 调用方提供

public:
    CxReq(WORD code);					// 无参数
    CxReq(WORD code, DWORD arg);		// 包含一个简单参数
    CxReq(WORD code, NPack* arg);		// 一个完整参数包
    virtual ~CxReq();

    virtual const char* Name(void) { return(""); }

    // 调用方
    // 在推送前附上返回数据容器，在请求处理后，调用方自主可读
    virtual void AttachReturnData(ReturnData* pReturnData) { m_pReturnData = pReturnData; }
    virtual void AttachSyncReturn(CxReturn* pSyncReturn) { m_pSyncReturn = pSyncReturn; }

    // 服务方
    virtual WORD   GetCode(void) { return(m_code); }
    virtual NPack* GetArg(void) { return(m_arg); }
    virtual void   SetReturnError(WORD errorCode) { m_pReturnData->m_error = errorCode; }
    virtual Ndata* GetReturnResult(void) { return(m_pReturnData->m_result); }
    virtual BOOL   IsSync(void) { return(m_pSyncReturn != NULL); }
    virtual void   PostSyncReturn(void) { m_pSyncReturn->Post(); }
};



class CxThread {
protected:

	bool	m_running;
	bool	m_stopSignal;
    CxReturn*	m_stopReturn;

public:
    char * m_name;
    TaskHandle_t  m_handel;	
	UBaseType_t m_uxPriority;
	CxThread(void);
	virtual ~CxThread();

	virtual bool IsActive(void) {return(m_running);}
	virtual void Start(void);
	virtual void PostStopSignal(void);
	virtual bool SyncStop(uint32_t msout);
	virtual void Run(void);				
};

void  RtxDelay(uint32_t ms);
uint32_t RtxGetRunMs(void);
void osThreadExit();
class SoftTimer {
protected:
	uint32_t	m_intvMs;
	bool	m_onceTick;
	bool	m_onceTickOccured;
	uint32_t	m_stateMs;

public:
	SoftTimer(uint32_t intvMs, bool onceTick = false);
	virtual ~SoftTimer() {}

	virtual void Reset(uint32_t ms);
	virtual bool OnTick(uint32_t ms);
};


#endif 
